# -*- coding: utf-8 -*-
import hall_callback
import t_const, t_error, t_cmd, t_wizard
import random, cPickle

#游戏逻辑类，单局游戏的全局数据保存在这里
class CMap(object):
	#构造函数
	def __init__(self, objRoom):
		super(CMap, self).__init__()
		self.objRoom = objRoom				#房间对象的引用，消息发送和写日志用到
		self.objMsgMgr = hall_callback.get_game_room_msgmgr()		#传输对象的引用，消息打包的时候用到
		self.register_recv()		#注册游戏子事件的响应函数
		self.reset()						#初始化游戏内全局数据


	#自我清理的函数，释放此对象前调用
	def clean(self):
		self.reset_map()
		self.reset()
		self.objRoom = None
		self.objMsgMgr = None

	#此函数注册游戏子事件的具体响应函数
	def register_recv(self):
		self.dicEventFunc = {}
		self.dicEventFunc[t_cmd.C_GAME_MOVE]	= self.send_game_onmove
		self.dicEventFunc[t_cmd.C_GAME_HITGEM]	= self.send_game_hitgem

	#此函数对游戏内全局数据进行初始化或重置
	def reset(self):
		self.iStatus = t_const.GAME_WAIT		#游戏状态，初始化为准备（非进行游戏）
		self.gametime = -1	# 游戏计时器
		self.iStage = None		#当前关卡，初始化为None
		self.iCurFrame = 0		#当前帧数，初始化为0
		self.objTimeLine = None		#管理怪物和阳光刷新数据的对象，初始化为None
		self.dicTrackSet = {}			#当前关卡的地形数据的字典，key是轨道编号，value是一个代表地形的int，可能为草地、水域或屋顶
		self.dicPlayers = {}			#管理当前游戏内玩家对象的字典，key是玩家的side，value是游戏内玩家对象
		self.dicPlayersuid = {}
		self.iWinScore = 0				#本局的胜利得分
		self.iLoseScore = 0				#本局的失败得分

		self.map = None

	#此函数释放和清理游戏内的全局数据，一般在游戏结束的时候调用
	def reset_map(self):
		self.gametime = None
		#清空地形数据字典
		#self.dicTrackSet.clear()

	#此函数生成一个可用的精灵id，并维护精灵id字典，大致算法是对当前已经用到的精灵id进行递增，并加入已用精灵字典，然后返回id
	def generate_id(self, iType):
		pass

	# 初始化游戏地图
	def on_game_init(self, stage, lstPlayer):
		#重置游戏内全局数据
		self.reset()
		#设置游戏状态为游戏中
		self.iStatus = t_const.GAME_PLAYING
		#保存当前关卡key
		self.iStage = stage

		# 游戏地图
		import t_map_s
		self.map = t_map_s.CMap(self.objRoom)
		self.map.load(stage)

		#初始化游戏内玩家对象
		import t_game_player_s
		for room_player in lstPlayer:
			objPlayer = t_game_player_s.CGameplayer(room_player, self.map.g_player_pos[len(self.dicPlayers)])
			self.dicPlayers[objPlayer.iside] = objPlayer
			self.dicPlayersuid[objPlayer.uid] = objPlayer
			#=======发送玩家初始属性
			self.send_player_info(objPlayer)
			self.send_player_pos(objPlayer)

		#读取关卡配置
		#config = td_stage_config.DATA.get(stage)
		# 游戏事件
		import t_evtmgr_s
		self.game_event = t_evtmgr_s.CGameEvtMgr(self, stage, self.dicPlayers)

		pass


	#此函数处理游戏开始的相关逻辑
	def on_game_start(self):
		#发送游戏开始消息
		self.send_game_start()
		self.game_event.begin()

	#此函数用于检测是否达到游戏胜利条件
	def check_game_end(self, second):
		#如果还有固定怪物未刷新，则不算胜利
		pass

	#此函数检测游戏中有效（未退出或失败）的玩家是否为0，假如有效玩家为0则游戏强制结束
	def check_empty_game(self):
		pass

	#此函数用于处理游戏结束的相关逻辑
	def game_end(self, win):
		#根据玩家当局的具体表现对游戏进行结算，并生成游戏内玩家对象的临时列表
		lstPlayer = []
		for player in self.dicPlayers.itervalues():
			player.on_game_end(win, self.iWinScore,	self.iLoseScore)
			lstPlayer.append(player)

		#游戏状态切换到准备
		self.iStatus = t_const.GAME_WAIT
		#调用房间逻辑的on_game_end函数，处理需要保留的历史数据
		return lstPlayer

	#此函数每个逻辑帧调用一次，处理时间驱动的逻辑
	def logic_frame(self):
		#当前帧数递增
		self.iCurFrame += 1
		#每秒一次发送游戏时间
		#if (self.iCurFrame % t_const.FPS_SERVER) == 0:
			#second = self.iCurFrame / t_const.FPS_SERVER
			#print self.iCurFrame
		#	self.send_gametime()
		# 事件
		#self.game_event.update()
		pass

	#此函数每秒调用一次，根据关卡配置刷新僵尸
	def generate_monster(self, second):
		pass

	#此函数每秒调用一次，根据关卡配置生成阳光
	def generate_sun(self, second):
		pass

	#此函数在游戏中玩家离开房间时由房间逻辑调用，记录此玩家不再是“有效玩家”，并判断是否因为全部为无效玩家而结束游戏
	def player_leave(self, iSide):
		pass

	#此函数在客户端发送游戏子事件时由房间逻辑调用，对子事件进行数据解包并根据子事件类型调用具体的子事件处理函数
	def on_game_event(self, iSide, frame, event, data):
		#print "server:on_game_event:",iSide,frame,event,data
		if self.dicEventFunc.has_key(event):
			param = [iSide, ]
			param.extend(cPickle.loads(data))
			apply(self.dicEventFunc[event], param)
		pass


#-------------------------------------------------向客户端广播消息
#---------------------主动发送消息
	#给指定玩家发送他的属性信息
	def send_player_info(self, objPlayer):
		param = (objPlayer.hp, objPlayer.speed, objPlayer.attack, objPlayer.defense, objPlayer.pos)
		self.send_game_event_p(objPlayer, t_cmd.S_INIT_INFO, param)
		pass

	def send_player_pos(self, objPlayer):
		param = (objPlayer.uid, objPlayer.pos)
		self.send_game_event_other(objPlayer, t_cmd.S_GAME_RUN, param)

#---------------------接收消息后返回
	def on_turend(self, obj, uid, rotate):
		param = (uid,rotate)
		self.send_game_event(t_cmd.S_TUREND, param)

	#玩家移动消息
	def send_game_onmove(self,obj, uid, ismove, dir, pos):
		param = (uid, ismove, dir, pos)
		objPlayer = self.dicPlayersuid[uid]
		self.send_game_event_other(objPlayer, t_cmd.S_GAME_MOVE, param)

	def send_game_hitgem(self, obj, uid, grid, dir):
		#print "收到玩家击打消息",grid,dir,uid
		param = (uid, grid, dir)
		objPlayer = self.dicPlayersuid[uid]
		self.send_game_event(t_cmd.S_GAME_HITGEM, param)

	def on_run(self, obj, uid, posx, posy):
		param = (uid, posx, posy)
		self.dicPlayersuid[uid].pos = (posx,posy)
		#print "update%s pos"%uid
		self.send_game_event(t_cmd.S_RUN, param)

	def on_atk(self, obj, uid, pos, dir, weapon):
		param = (uid, pos, dir, weapon)
		self.send_game_event(t_cmd.S_ATK, param)

	def on_pickitem(self, obj, uid, names):
		param = (uid, names)
		# 判断拾取
		if self.dicPlayersuid[uid].pickItem(names):
			self.send_game_event(t_cmd.S_PICKITEM, param)

	# 游戏时间发送
	def send_gametime(self):
		self.gametime += 1
		param = (self.gametime, 0)

#----------------------------------------------------------------
	# 所有玩家都初始化完成,发送游戏开始消息
	def send_game_start(self):
		obj = self.objMsgMgr.game_s_game_start_sec(side=1)
		self.objRoom.send_all(obj)

	#打包并发送游戏子事件的消息，frame：子事件发生的服务端时间帧；event_id：子事件类型；param：子事件具体参数（使用cPickle打包成一个字符串）
	def send_game_event(self, event, param_list):
		_str = cPickle.dumps(param_list)
		obj = self.objMsgMgr.game_s_game_event(frame=self.iCurFrame, event_id=event, param=_str)
		self.objRoom.send_all(obj)

	# 除某人外的其它人
	def send_game_event_other(self, objPlayer, event, param_list):
		_str = cPickle.dumps(param_list)
		obj = self.objMsgMgr.game_s_game_event(frame=self.iCurFrame, event_id=event, param=_str)
		exclude = []
		exclude.append(objPlayer.hid)
		self.objRoom.send_all(obj, exclude)
	# 指定发送玩家
	def send_game_event_p(self, objPlayer, event, param_list):
		_str = cPickle.dumps(param_list)
		obj = self.objMsgMgr.game_s_game_event(frame=self.iCurFrame, event_id=event, param=_str)
		self.objRoom.send_to_user(objPlayer, obj)
		pass
